package com.enjoyor.soa.traffic.frame.configure;

import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.TypeHandler;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.enjoyor.soa.traffic.frame.handler.mybatis.OraclClobTypeHandler;
import com.enjoyor.soa.traffic.frame.handler.mybatis.SdoGeometryTypeHandler;
import com.enjoyor.soa.traffic.frame.interceptor.PageInterceptor;
import com.enjoyor.soa.traffic.frame.interceptor.SqlInterceptor;

@Configuration
@PropertySource({ "classpath:mybatis.properties" })
public class MyBatisConfig implements TransactionManagementConfigurer {

    @Bean
    public DataSource dataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Value("${mybatis.page.interceptor.showSql}")
    private String showSql;

    @Value("${mybatis.page.interceptor.databaseType}")
    private String databaseType;

    @Value("${mybatis.type.aliasesPackage}")
    private String aliasesPackage;

    @Value("${mybatis.type.handlersPackage}")
    private String handlersPackage;

    @Value("${mybatis.mapper.location}")
    private String location;

    @SuppressWarnings("rawtypes")
    @Bean(name = { "sqlSessionFactory" })
    public SqlSessionFactory sqlSessionFactoryBean() {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();

        bean.setDataSource(dataSource());

        bean.setVfs(SpringBootVFS.class);

        bean.setTypeAliasesPackage(aliasesPackage);

        Class<?>[] clazzs = { oracle.spatial.geometry.JGeometry.class };

        bean.setTypeAliases(clazzs);

        bean.setTypeHandlersPackage(handlersPackage);

        SdoGeometryTypeHandler sdoGeometryTypeHandler = new SdoGeometryTypeHandler();

        OraclClobTypeHandler oraclClobTypeHandler = new OraclClobTypeHandler();

        TypeHandler[] typeHandlers = { sdoGeometryTypeHandler, oraclClobTypeHandler };

        bean.setTypeHandlers(typeHandlers);

        Properties properties1 = new Properties();
        properties1.setProperty("showSql", this.showSql);

        Properties properties2 = new Properties();
        properties2.setProperty("databaseType", this.databaseType);

        // Sql语句
        SqlInterceptor sqlInterceptor = new SqlInterceptor();
        sqlInterceptor.setProperties(properties1);

        // 分页插件
        PageInterceptor pageInterceptor = new PageInterceptor();
        pageInterceptor.setProperties(properties2);

        Interceptor[] plugins = { pageInterceptor, sqlInterceptor };
        bean.setPlugins(plugins);

        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        try {
            bean.setMapperLocations(resolver.getResources(location));
            return bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

}
